{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# tensorflow 变量\n",
    "tensorflow 变量是表示程序操作的共享性、持久性的最好方法。\n",
    "\n",
    "变量是通过 [tf.Variable](https://tensorflow.google.cn/api_docs/python/tf/Variable) 类进行操作的，一个 tf.Variable 表示一个在操作进行中可以改变的 tensor。一些特定的操作允许你读取和修改这个 tensor 的值，像是高级 API 中 tf.Keras 使用 tf.Variable 来存储模型参数。这个教程旨在展示如何在 tensorflow 中创建、更新和管理 tf.Variable\n",
    "\n",
    "## 创建一个变量\n",
    "要创建变量，只需要提供初始值\n",
    "```python\n",
    "my_variable = tf.Variable(tf.zeros([1, 2, 3]))\n",
    "```\n",
    "上面创建了一个维度为 [1, 2, 3]，值全为 0 的变量，这个变量的 dtype 将默认使用 tf.float32，如果没有指定，则从初始值中推断 dtype。\n",
    "\n",
    "如果有 tf.device 作用域处于活动状态，则这个变量将被设置在这个设备上；其它的变量将被设置在离兼容它的 dtype 的最近的设备（这意味着如果有一个 GPU 是可用的，大多数的变量将被自动设置在该 CPU 上）。例如，以下代码块创建了一个名字为 v 的变量并将它设置在第二个 GPU 上：\n",
    "```python\n",
    "with tf.device(\"/device:GPU:1\"):\n",
    "    v = tf.Variable(tf.zeros([10, 10]))\n",
    "```\n",
    "\n",
    "理想状态下，你应该使用 [tf.distribute](https://tensorflow.google.cn/api_docs/python/tf/distribute) API，只要你有一次编写代码，就能在很多分布式设置下工作。\n",
    "\n",
    "## 使用变量\n",
    "对于 tf.Variable 的使用，像是使用普通的 tf.Tensor：\n",
    "```python\n",
    "v = tf.Variable(0.0)\n",
    "w = v + 1 # w 是基于 v 的值计算的 tf.Tensor，任何时候一个变量被用于一个表达式的计算，它会自动将自己的值转换为一个 tf.Tensor\n",
    "```\n",
    "\n",
    "要为一个变量赋值，应使用 tf.Variable 类的 assign、assign_add、friends 方法。比如，下例展示了如果调用这些方法：\n",
    "```python\n",
    "v = tf.Variable(0.0)\n",
    "v.assign_add(1)\n",
    "```\n",
    "\n",
    "大多数的 tensorflow 优化器有特殊的操作以在梯度下降算法中更高效地修改变量，可以查看 [tf.keras.optimizers.Optimizer](https://tensorflow.google.cn/api_docs/python/tf/keras/optimizers/Optimizer) 获取如何使用优化器的说明。\n",
    "\n",
    "你也能使用 read_value 显式地读取当前变量的值：\n",
    "```python\n",
    "v = tf.Variable(0.0)\n",
    "v.assign_add(1)\n",
    "v.read_value()\n",
    "```\n",
    "\n",
    "当当前域 tf.Variable 的最后一次引用被丢弃后，它的内存会被释放。\n",
    "\n",
    "### 跟踪变量\n",
    "在 tensorflow 中一个变量是一个 python 变量，当你创建你的图层、模型、优化器和其它相关工具时，你可能想在模型中获取一个记录所有变量的列表。\n",
    "\n",
    "一个普遍的方法是使用继承了 Layer 类的子类，这个 Layer 类递归跟踪设置为实例属性的变量：\n",
    "```python\n",
    "class MyLayer(tf.keras.layers.Layer):\n",
    "    def __init__(self):\n",
    "        super(MyLayer, self).__init__()\n",
    "        self.my_var = tf.Variable(1.0)\n",
    "        self.my_var_list = [tf.Variable(x) for x in rang(10)]\n",
    "\n",
    "class MyOtherLayer(tf.keras.layers.Layer):\n",
    "    def __init__(self):\n",
    "        super(MyOtherLayer, self).__init__()\n",
    "        self.sublayer = MyLayer()\n",
    "        self.my_other_var = tf.Variable(10.0)\n",
    " \n",
    "m = MyOtherLayer()\n",
    "print(len(m.variables))\n",
    "```\n",
    "\n",
    "如果你不想扩展一个新的图层，tensorflow 还有一个更通用的只用于实现变量跟踪的 tf.Model 基类。tf.Model 实例有一个 variables 和一个 trainable_variables 属性，用于返回在模型中可获得的所有（训练）变量，"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6rc1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
